{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Embedded kernels \n",
    "\n",
    "This notebook and the C# project in this folder demonstrates how you can use .NET Interactive to embed a kernel within an app, connect to it from another kernel, and use the notebook to change the app's runtime state.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "## Connect to the WPF app\n",
    "\n",
    "First, let's start the WPF app and connect to it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "dotnet_interactive": {
     "language": "pwsh"
    }
   },
   "outputs": [],
   "source": [
    "Start-Process -NoNewWindow dotnet run"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "System.Diagnostics.Debugger.Launch();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once the cell above has finished running, you should see the WPF app window open. Next, we'll connect to it using a named pipe. The code that sets up the embedded kernel and the named pipe within the WPF app can be seen in [`App.xaml.cs`](https://github.com/dotnet/interactive/blob/main/samples/connect-wpf/App.xaml.cs).\n",
    "\n",
    "To connect using a named pipe, we'll need the following package:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div><div><strong>Restore sources</strong><ul><li><span> c:\\temp\\packages</span></li></ul></div><div></div><div><strong>Installed Packages</strong><ul><li><span>Microsoft.DotNet.Interactive.NamedPipeConnector, 2.0.0</span></li></ul></div></div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "Loading extension script from `C:\\Users\\josequ\\.nuget\\packages\\microsoft.dotnet.interactive.namedpipeconnector\\2.0.0\\interactive-extensions\\dotnet\\extension.dib`"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#i \"nuget: c:\\temp\\packages\"\n",
    "#r \"nuget: Microsoft.DotNet.Interactive.NamedPipeConnector,*-*\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The package adds the `#!connect named-pipe` magic command:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "dotnet_interactive": {
     "language": "csharp"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Kernel added: #!wpf"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#!connect named-pipe --kernel-name wpf --pipe-name InteractiveWpf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The topology of connected kernels now looks like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "polyglot_notebook": {
     "kernelName": "mermaid"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div class=\"mermaidMarkdownContainer\" style=\"background-color:white\">\r\n",
       "<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css\">\r\n",
       "<div id=\"192be5b02d6542978c1d1e766ca59120\"></div>\r\n",
       "<script type=\"module\">\r\n",
       "\r\n",
       "            import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10.6.1/dist/mermaid.esm.min.mjs';\r\n",
       "            let renderTarget = document.getElementById('192be5b02d6542978c1d1e766ca59120');\r\n",
       "            try {\r\n",
       "                const {svg, bindFunctions} = await mermaid.mermaidAPI.render( \r\n",
       "                    'mermaid_192be5b02d6542978c1d1e766ca59120', \r\n",
       "                    `flowchart LR\n",
       "    subgraph WPF app\n",
       "    embedded[\"Embedded C# kernel\"]\n",
       "    end\n",
       "    subgraph notebook\n",
       "    CompositeKernel-->n1[\"Local C# kernel\"]\n",
       "    CompositeKernel-->n2\n",
       "    n2[\"#!wpf kernel added using #!connect\"]--named pipe-->embedded\n",
       "    end`);\r\n",
       "                renderTarget.innerHTML = svg;\r\n",
       "                bindFunctions?.(renderTarget);\r\n",
       "            }\r\n",
       "            catch (error) {\r\n",
       "                console.log(error);\r\n",
       "            }\r\n",
       "</script>\r\n",
       "</div>\r\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "flowchart LR\n",
    "    subgraph WPF app\n",
    "    embedded[\"Embedded C# kernel\"]\n",
    "    end\n",
    "    subgraph notebook\n",
    "    CompositeKernel-->n1[\"Local C# kernel\"]\n",
    "    CompositeKernel-->n2\n",
    "    n2[\"#!wpf kernel added using #!connect\"]--named pipe-->embedded\n",
    "    end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Change the styling of the app\n",
    "\n",
    "The notebook outputs here are displayed using custom formatters defined within the WPF app itself. Take a look at the file [`WpfFormatterMixins.cs`](https://github.com/dotnet/interactive/blob/main/samples/connect-wpf/WpfFormatterMixins.cs).\n",
    "\n",
    "You'll also notice that you can get completions for the `App` object which is exposed to the notebook's kernel by the embedded kernel. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "dotnet_interactive": {
     "language": "wpf"
    },
    "polyglot_notebook": {
     "kernelName": "wpf"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div><div style=\"border:2px solid #FFFFFF;background-color:#DDA0DDFF;width:15px;height:15px\"></div><div><b>#DDA0DDFF</b></div></div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#!dispatcher\n",
    "using System.Windows.Media;\n",
    "\n",
    "App.MainWindow.Background = new SolidColorBrush(Colors.Plum);\n",
    "App.MainWindow.Background"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "dotnet_interactive": {
     "language": "wpf"
    },
    "polyglot_notebook": {
     "kernelName": "wpf"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<img src=\"data:image/png;base64, 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AACECQgAACBMQAAAAGECAgAACBMQAABAmIAAAADCBAQAABAmIAAAgDABAQAAhAkIAAAgTEAAAABhAgIAAAgTEAAAQJiAAAAAwgQEAAAQJiAAAIAwAQEAAIQJCAAAIExAAAAAYQICAAAIExAAAECYgAAAAMIEBAAAECYgAACAMAEBAACECQgAACBMQAAAAGECAgAACBMQAABAmIAAAADCBAQAABAmIAAAgDABAQAAhAkIAAAgTEAAAABhAgIAAAgTEAAAQJiAAAAAwgQEAAAQJiAAAIAwAQEAAIQJCAAAIExAAAAAYQICAAAIExAAAECYgAAAAMIEBAAAECYgAACAMAEBAACECQgAACBMQAAAAGECAgAACBMQAABAmIAAAADCBAQAABAmIAAAgDABAQAAhAkIAAAgTEAAAABhAgIAAAgTEAAAQJiAAAAAwgQEAAAQJiAAAIAwAQEAAIQJCAAAIExAAAAAYQICAAAIExAAAECYgAAAAMIEBAAAECYgAACAMAEBAACECQgAACBMQAAAAGECAgAACBMQAABAmIAAAADCBAQAABAmIAAAgDABAQAAhAkIAAAgTEAAAABhAgIAAAgTEAAAQJiAAAAAwgQEAAAQJiAAAIAwAQEAAIQJCAAAIExAAAAAYQICAAAIExAAAECYgAAAAMIEBAAAECYgAACAMAEBAACECQgAACBMQAAAAGECAgAACBMQAABAmIAAAADCBAQAABAmIAAAgDABAQAAhAkIAAAgTEAAAABhAgIAAAgTEAAAQJiAAAAAwgQEAAAQJiAAAIAwAQEAAIQJCAAAIExAAAAAYQICAAAIExAAAECYgAAAAMIEBAAAECYgAACAMAEBAACECQgAACBMQAAAAGECAgAACBMQAABAmIAAAADCBAQAABAmIAAAgDABAQAAhAkIAAAgTEAAAABhAgIAAAgTEAAAQJiAAAAAwgQEAAAQJiAAAIAwAQEAAIQJCAAAIExAAAAAYQICAAAIExAAAECYgAAAAMIEBAAAECYgAACAMAEBAACECQgAACBMQAAAAGECAgAACBMQAABAmIAAAADCBAQAABAmIAAAgDABAQAAhAkIAAAgTEAAAABhAgIAAAgTEAAAQJiAAAAAwgQEAAAQJiAAAIAwAQEAAIQJCAAAIExAAAAAYQICAAAIExAAAECYgAAAAMIEBAAAECYgAACAMAEBAACECQgAACBMQAAAAGECAgAACBMQAABAmIAAAADCBAQAABAmIAAAgDABAQAAhAkIAAAgTEAAAABhAgIAAAgTEAAAQJiAAAAAwgQEAAAQJiAAAIAwAQEAAIQJCAAAIExAAAAAYQICAAAIExAAAECYgAAAAMIEBAAAECYgAACAMAEBAACECQgAACBMQAAAAGECAgAACBMQAABAmIAAAADCBAQAABAmIAAAgDABAQAAhAkIAAAgTEAAAABhAgIAAAgTEAAAQJiAAAAAwgQEAAAQJiAAAIAwAQEAAIT9H1DKXa063GOSAAAAAElFTkSuQmCC\" width=\"784\" height=\"411\"></img>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#!dispatcher\n",
    "using System.Windows.Media;\n",
    "using System.Windows.Controls;\n",
    "using System.Windows;\n",
    "\n",
    "var content = (Grid)App.MainWindow.Content;\n",
    "content.Background = new SolidColorBrush(Colors.RoyalBlue);\n",
    "content.UpdateLayout();\n",
    "content"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Change view models at runtime\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Create and apply a new view model to the main window."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "dotnet_interactive": {
     "language": "wpf"
    },
    "polyglot_notebook": {
     "kernelName": "wpf"
    }
   },
   "outputs": [],
   "source": [
    "using System.ComponentModel;\n",
    "using System.Collections.ObjectModel;\n",
    "\n",
    "public class TestViewModel : INotifyPropertyChanged\n",
    "{\n",
    "    public event PropertyChangedEventHandler PropertyChanged;\n",
    "\n",
    "    private string _text = \"Initial Value from notebook view model\";\n",
    "    \n",
    "    public string Text\n",
    "    {\n",
    "        get => _text;\n",
    "        set\n",
    "        {\n",
    "            if (_text != value)\n",
    "            {\n",
    "                _text = value;\n",
    "                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(nameof(Text)));\n",
    "            }\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "var vm = new TestViewModel();\n",
    "\n",
    "#!wpf\n",
    "#!dispatcher\n",
    "App.MainWindow.DataContext = vm;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Update the value on the data bound property."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "dotnet_interactive": {
     "language": "wpf"
    },
    "polyglot_notebook": {
     "kernelName": "wpf"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Value changed!"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "vm.Text = \"Value changed!\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " ## `#dispatcher`\n",
    "\n",
    " The following demonstrate specifying whether to run code on the dispatcher."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "dotnet_interactive": {
     "language": "wpf"
    },
    "polyglot_notebook": {
     "kernelName": "wpf"
    }
   },
   "outputs": [],
   "source": [
    "#!dispatcher \n",
    "//This should work\n",
    "App.MainWindow.Title = \"Title change executed on dispatcher thread\";\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "dotnet_interactive": {
     "language": "wpf"
    },
    "polyglot_notebook": {
     "kernelName": "wpf"
    }
   },
   "outputs": [
    {
     "ename": "Error",
     "evalue": "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.\r\n   at System.Windows.Threading.Dispatcher.<VerifyAccess>g__ThrowVerifyAccess|7_0()\r\n   at System.Windows.Application.get_MainWindow()\r\n   at Submission#9.<<Initialize>>d__0.MoveNext()\r\n--- End of stack trace from previous location ---\r\n   at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)",
     "output_type": "error",
     "traceback": [
      "System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.\r\n",
      "   at System.Windows.Threading.Dispatcher.<VerifyAccess>g__ThrowVerifyAccess|7_0()\r\n",
      "   at System.Windows.Application.get_MainWindow()\r\n",
      "   at Submission#9.<<Initialize>>d__0.MoveNext()\r\n",
      "--- End of stack trace from previous location ---\r\n",
      "   at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)"
     ]
    }
   ],
   "source": [
    "\n",
    "//This is expected to fail\n",
    "App.MainWindow.Title = \"Not so much\";"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "file_extension": ".cs",
   "mimetype": "text/x-csharp",
   "name": "polyglot-notebook",
   "pygments_lexer": "csharp",
   "version": "8.0"
  },
  "polyglot_notebook": {
   "kernelInfo": {
    "defaultKernelName": "csharp",
    "items": [
     {
      "aliases": [],
      "name": "csharp"
     },
     {
      "aliases": [],
      "languageName": "T-SQL",
      "name": "sql-adventureworks"
     },
     {
      "aliases": [],
      "name": "wpf"
     }
    ]
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
